import { INode } from '@/render/store/configdef/types'

function handleModel(model: any): INode | null {
  const module: INode = {
    id: model.UUID,
    data: {
      label: model.name,
      isNew: model.isNew,
      type: 'module',
      description: model.description,
      lowerMultiplicity: model.lowerMultiplicity,
      upperMultiplicity: model.upperMultiplicity,
      compileTimeType: model.compileTimeType
    },
    children: handleContainers(model.UUID, model.containers)
  }
  return module
}

function handleContainers(parentId: string, containers: any): INode[] | null {
  if (containers == null) {
    return null
  }
  const containersTemp = []
  for (let index = 0; index < containers.length; index++) {
    const element = containers[index]
    const containerTemp: INode = {
      id: element.UUID,
      parentId: parentId,
      data: {
        label: element.name,
        type: 'container',
        isNew: element.isNew,
        lowerMultiplicity: element.lowerMultiplicity,
        description: element.description,
        upperMultiplicity: element.upperMultiplicity
      },
      children: []
    }
    const subContainers: INode[] | null = handleSubContainers(
      containerTemp.id,
      element.subContainers
    )
    if (subContainers) containerTemp.children?.push(...subContainers)
    const parameters = handleParameters(containerTemp.id, element.parameters)
    if (parameters) containerTemp.children?.push(...parameters)
    const references = handleReferences(containerTemp.id, element.references)
    if (references) containerTemp.children?.push(...references)
    containersTemp.push(containerTemp)
  }
  return containersTemp
}
function handleSubContainers(
  parentId: string,
  subContainers: any
): INode[] | null {
  if (subContainers == null) {
    return null
  }
  const subContainersTemp: INode[] = []
  subContainers.forEach((element: any) => {
    const subContainerTemp: INode = {
      id: element.UUID,
      parentId: parentId,
      data: {
        label: element.name,
        type: 'subContainer',
        isNew: element.isNew,
        lowerMultiplicity: element.lowerMultiplicity,
        description: element.description,
        upperMultiplicity: element.upperMultiplicity
      },
      children: []
    }
    const subContainers: INode[] | null = handleSubContainers(
      subContainerTemp.id,
      element.subContainers
    )
    if (subContainers) {
      subContainerTemp.children?.push(...subContainers)
    }
    const parameters: INode[] | null = handleParameters(
      subContainerTemp.id,
      element.parameters
    )
    if (parameters) {
      subContainerTemp.children?.push(...parameters)
    }
    const references: INode[] | null = handleReferences(
      subContainerTemp.id,
      element.references
    )
    if (references) {
      subContainerTemp.children?.push(...references)
    }

    subContainersTemp.push(subContainerTemp)
  })
  return subContainersTemp
}
function handleParameters(parentId: string, parameters: any): INode[] | null {
  if (parameters == null) {
    return null
  }
  const parametersTemp: INode[] = []
  for (let index = 0; index < parameters.length; index++) {
    const element = parameters[index]
    const parameterTemp: INode = {
      id: element.UUID,
      parentId: parentId,
      data: {
        label: element.name,
        type: 'parameter',
        isNew: element.isNew,
        description: element.description,
        lowerMultiplicity: element.lowerMultiplicity,
        upperMultiplicity: element.upperMultiplicity,
        parameterType: element.type,
        defaultValue: element.defaultValue,
        max: '',
        min: ''
      },
      children: []
    }
    if (
      parameterTemp.data.parameterType === 'integer' ||
      parameterTemp.data.parameterType === 'float'
    ) {
      parameterTemp.data.max = element.max
      parameterTemp.data.min = element.min
    } else if (parameterTemp.data.parameterType === 'enumeration') {
      const literalsTemp: INode[] | null = handleLiterals(
        parameterTemp.id,
        element.literals
      )
      if (literalsTemp) {
        parameterTemp.children?.push(...literalsTemp)
      }
    }
    parametersTemp.push(parameterTemp)
  }
  return parametersTemp
}
function handleReferences(parentId: string, references: any): INode[] | null {
  if (references == null) {
    return null
  }
  const referencesTemp: INode[] = []
  for (let index = 0; index < references.length; index++) {
    const element = references[index]
    const referenceTemp: INode = {
      id: element.UUID,
      parentId: parentId,
      data: {
        label: element.name,
        isNew: element.isNew,
        type: 'reference',
        referenceType: element.type,
        description: element.description,
        lowerMultiplicity: element.lowerMultiplicity,
        upperMultiplicity: element.upperMultiplicity
      },
      children: []
    }
    const destinationsTemp = handleDestination(
      referenceTemp.id,
      element.destinations
    )
    if (destinationsTemp) {
      referenceTemp.children?.push(...destinationsTemp)
    }

    referencesTemp.push(referenceTemp)
  }
  return referencesTemp
}
function handleLiterals(parentId: string, literals: any): INode[] | null {
  if (literals == null) {
    return null
  }
  const literalsTemp: INode[] = []
  for (let index = 0; index < literals.length; index++) {
    const element = literals[index]
    const literalTemp: INode = {
      id: element.UUID,
      parentId: parentId,
      data: {
        label: element.name,
        isNew: element.isNew,
        type: 'literal'
      },
      children: []
    }
    literalsTemp.push(literalTemp)
  }
  return literalsTemp
}
function handleDestination(
  parentId: string,
  destinations: any
): INode[] | null {
  if (destinations == null) {
    return null
  }
  const destinationsTemp: INode[] = []
  for (let index = 0; index < destinations.length; index++) {
    const element = destinations[index]
    const destinationTemp: INode = {
      id: `${parentId}_${element.name}`,
      parentId: parentId,
      data: {
        label: element.name,
        isNew: element.isNew,
        type: 'destination'
      },
      children: []
    }
    destinationsTemp.push(destinationTemp)
  }
  return destinationsTemp
}

export default handleModel
